<?php

namespace App\Http\Controllers;

use App\Dao\TicketOrderDao;
use App\Models\TicketOrder;
use App\Models\TicketOrderItem;
use App\Models\TicketOrderRefundLog;
use App\Models\TicketPayment;
use App\Models\Users;
use App\Utilities\Alipay\AopClient;
use EasyWeChat\Factory;
use GuzzleHttp\Client;

class PaymentController extends Controller
{

	/**
	 * 微信小程序支付异步通知
	 *
	 * @author lxp
	 * @return \Symfony\Component\HttpFoundation\Response
	 * @throws \EasyWeChat\Kernel\Exceptions\Exception
	 */
	public function wx_mini_notify()
	{
		return $this->wx_notify(PAYMENT_ID_WXPAY_MINI);
	}

	/**
	 * 微信支付异步通知
	 *
	 * @author lxp 20180823
	 * @param int $payment_id 支付方式id
	 * @return \Symfony\Component\HttpFoundation\Response
	 * @throws \EasyWeChat\Kernel\Exceptions\Exception
	 */
	public function wx_notify($payment_id = PAYMENT_ID_WXPAY)
	{
		$logObj = app('logext');
		$logObj->init('wxpay_notify');

		// 取得支付方式相关信息
		$payment = TicketPayment::select(['payment_info'])->find($payment_id);
		$payment_info = unserialize($payment->payment_info);

		$wxapp = Factory::payment([
			'app_id' => $payment_info['wxAppId'],
			'mch_id' => $payment_info['wxMchId'],
			'key' => $payment_info['wxkey']
		]);

		$response = $wxapp->handlePaidNotify(function ($message, $fail) use ($logObj, $payment_id) {
			$logObj->logbuffer('message', $message);

			// 取得订单
			$torder = TicketOrder::where('out_trade_no', $message['out_trade_no'])->first([
				'torder_id',
				'order_status'
			]);
			if (is_null($torder)) {
				// 订单不存在
				$logObj->logbuffer('order_find_fail', $message['out_trade_no']);
				return $fail('order find fail');
			}

			if ($torder->order_status != T_ORDER_UNPAY) {
				if ($torder->order_status == T_ORDER_CANCELED) {
					// 订单已取消可支付成功
					$logObj->logbuffer('order_cancel_to_pay', '');
				} elseif ($torder->order_status == T_ORDER_FINISH) {
					// 订单支付完成
					$logObj->logbuffer('order_has_paid', '');
					return true;
				} else {
					// 订单状态异常
					$logObj->logbuffer('order_status_fail', $torder->order_status);
					return $fail('order status fail');
				}
			}

			if ($message['return_code'] === 'SUCCESS') {
				// 通信成功
				if (array_get($message, 'result_code') === 'SUCCESS') {
					// 支付成功
					TicketOrderDao::finish($torder->torder_id, $payment_id, true);
					$torder->transaction_no=$message['transaction_id'];
                    $torder->save();
					$logObj->logbuffer('SUCCESS', '');
				} elseif (array_get($message, 'result_code') === 'FAIL') {
					// 支付失败
					$logObj->logbuffer('order_pay_fail', '');
					return $fail('order pay fail');
				}
			} else {
				// 通信失败
				$logObj->logbuffer('notify_fail', '');
				return $fail('notify fail');
			}

			// 处理完成
			return true;
		});

		$logObj->logend();
		return $response;
	}

	/**
	 * 微信扫码异步通知
	 *
	 * @author lxp 20190415
	 * @return \Symfony\Component\HttpFoundation\Response
	 * @throws \EasyWeChat\Kernel\Exceptions\Exception
	 */
	public function wx_web_notify()
	{
		$logObj = app('logext');
		$logObj->init('wxpay_notify_web');

		// 取得支付方式相关信息
		$payment = TicketPayment::select(['payment_info'])->find(PAYMENT_ID_WXPAY);
		$payment_info = unserialize($payment->payment_info);

		$wxapp = Factory::payment([
			'app_id' => $payment_info['wxAppId'],
			'mch_id' => $payment_info['wxMchId'],
			'key' => $payment_info['wxkey']
		]);

		$response = $wxapp->handleScannedNotify(function ($message, $fail, $alert) use ($wxapp, $payment_info, $logObj) {
			$logObj->logbuffer('message', $message);

			// 取得扫码标识id
			$product_id = $message['product_id'];
			$product_info = explode('_', $product_id);
			if (!isset($product_info[0])) {
				$logObj->logbuffer('product_fail', '');
				return $fail('product fail');
			}
			$wxpay_params = [
				'trade_type' => 'NATIVE',
				'openid' => $message['openid'],
				'product_id' => $message['product_id']
			];
			// 根据订单号规则进行转发
			switch ($product_info[0]) {
				case 'pw':
					// 取得订单
					$torder = TicketOrder::where([
						'torder_id' => $product_info[1],
						'order_status' => T_ORDER_UNPAY
					])->first([
						'torder_id',
						'uid',
						'order_amount'
					]);
					if (is_null($torder)) {
						$logObj->logbuffer('order_fail', $product_info);
						return $fail('order fail');
					}
					$torder->out_trade_no = $torder->order_sn . 'S' . rand(1000, 9999);
					$torder->save();

					if ($torder->uid) {
						$uinfo = Users::where(['uid' => $torder->uid])->first([
							'uid',
							'is_test'
						]);
//						if (!is_null($uinfo) && $uinfo->is_test == 1) {
//							// 测试用户金额
//							$torder->order_amount = TicketOrderItem::where('discount_price', '>', 0)->where('torder_id', $torder->torder_id)->count() * 0.01;
//						}
					}

					$wxpay_params['body'] = '滨海科技馆参观票';
					$wxpay_params['out_trade_no'] = $torder->out_trade_no;
					$wxpay_params['total_fee'] = intval($torder->order_amount * 100);
					$wxpay_params['notify_url'] = $payment_info['notify_url'];
					break;

				default:
					$logObj->logbuffer('plat_fail', '');
					return $fail('plat fail');
					break;
			}

			$logObj->logbuffer('unify_params', $wxpay_params);
			// 统一下单
			$result = $wxapp->order->unify($wxpay_params);
			$logObj->logbuffer('unify_result', $result);
			// 判断支付结果
			if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
				$logObj->logbuffer('success', '');
				return $result['prepay_id'];
			} else {
				$logObj->logbuffer('prepay_fail', '');
				return $fail('prepay fail');
			}
		});

		$logObj->logend();
		return $response;
	}

	/**
	 * 支付宝支付异步通知
	 *
	 * @author lxp 20190528
	 * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
	 */
	public function ali_notify()
	{
		if (request('out_biz_no')) {
			// 支付宝异步退款处理
			return $this->_ali_notify_refund();
		}

		$logObj = app('logext');
		$logObj->init('alipay_notify');
		// 支付宝通用验证
		$check_r = $this->_ali_notify_check();
		if ($check_r !== true) {
			$logObj->logbuffer('common_check_fail', $check_r);
			$logObj->logend();
			return response($check_r);
		}

		// 根据外部订单号查找订单
		$torder = TicketOrder::where([
			'out_trade_no' => request('out_trade_no')
		])->first([
			'torder_id',
			'order_status',
			'order_amount',
			'uid'
		]);
		if (is_null($torder)) {
			// 订单不存在
			$logObj->logbuffer('order_find_fail', request('out_trade_no'));
			$logObj->logend();
			return response('order find fail');
		}

		// 验证订单状态
		if ($torder->order_status != T_ORDER_UNPAY) {
			if ($torder->order_status == T_ORDER_CANCELED) {
				// 订单已取消可支付成功
				$logObj->logbuffer('order_cancel_to_pay', '');
			} elseif ($torder->order_status == T_ORDER_FINISH) {
				// 订单支付完成
				$logObj->logbuffer('order_has_paid', '');
				// 通知支付宝不要再发送通知
				$logObj->logend();
				return response('success');
			} else {
				// 订单状态异常
				$logObj->logbuffer('order_status_fail', $torder->order_status);
				$logObj->logend();
				return response('order status fail');
			}
		}

		// 订单支付成功
		TicketOrderDao::finish($torder->torder_id, PAYMENT_ID_ALIPAY, true);
        $torder->transaction_no=request('trade_no');
        $torder->save();
		$logObj->logbuffer('SUCCESS', '');
		$logObj->logend();
		return response('success');
	}

	/**
	 * 支付宝异步通知
	 *
	 * @author lxp 20181023
	 * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
	 */
	private function _ali_notify_refund()
	{
		$logObj = app('logext');
		$logObj->init('alipay_notify_refund');

		// 支付宝通用验证
		$check_r = $this->_ali_notify_check('TRADE_CLOSED');
		if ($check_r !== true) {
			$logObj->logbuffer('common_check_fail', $check_r);
			$logObj->logend();
			return response($check_r);
		}

		// 根据外部订单号查找订单
		$torder = TicketOrder::where([
			'out_trade_no' => request('out_trade_no')
		])->first(['torder_id']);
		if (is_null($torder)) {
			// 订单不存在
			$logObj->logbuffer('order_find_fail', request('out_trade_no'));
			$logObj->logend();
			return response('order find fail');
		}

		// 查找退款订单
		$torder_refund = TicketOrderRefundLog::where([
			'torder_id' => $torder->torder_id,
			'refund_trade_no' => request('out_biz_no')
		])->first([
			'refund_fee'
		]);
		if (is_null($torder_refund)) {
			// 退款订单不存在
			$logObj->logbuffer('order_refund_find_fail', request('out_biz_no'));
			$logObj->logend();
			return response('order refund find fail');
		}

		// 更改退款订单状态
		$torder_refund->refund_status = REFUND_STATUS_SUCCESS;
		$torder_refund->refund_response_sync = json_encode(request()->all());
		$torder_refund->save();

		$logObj->logbuffer('SUCCESS', '');
		$logObj->logend();
		return response('success');
	}

	/**
	 * 支付宝通用验证
	 *
	 * @author lxp 20190528
	 * @param string $check_trade_status 需要检查匹配的订单状态
	 * @return bool|string
	 */
	private function _ali_notify_check($check_trade_status = 'TRADE_SUCCESS')
	{
		// 取得支付方式相关信息
		$payment = TicketPayment::select(['payment_info'])->find(PAYMENT_ID_ALIPAY);
		$payment_info = unserialize($payment->payment_info);

		$alipay = new AopClient();
		$alipay->alipayrsaPublicKey = file_get_contents($payment_info['public_key_path']);

        $signVerified = $alipay->rsaCheckV1(request()->all(), '', 'RSA2');
		if ($signVerified !== true) {
			return 'sign verifiy fail';
		}

		// 交易状态判断
		if (request('trade_status') != $check_trade_status) {
			return 'trade status fail';
		}

		// 验证APPID
		if (request('app_id') != $payment_info['appId']) {
			return 'appid check fail';
		}

		return true;
	}
}